# -*- coding: utf-8 -*-

import os
import re
import pytz
import datetime
import email.utils
import mailbox

from src.message import Email 
from src.tree import Tree, TreeNode

class Archive(object):
    """
    This class represents all emails of a month.
    """    
    
    def __init__(self, filename):
        """
        Constructor.
        """
        
        self.filename = filename
        
    def parse(self):
        if os.path.exists(self.filename):
            mb = mailbox.mbox(self.filename)
            emails = []
            for msg in mb:
                emails.append(msg)
            
            return emails
        else:
            raise IOError("File not found.")
                    
        
    
    # fazer em 3 passos
    # 1 - colocar todas as mensagens num dicionario com seu id como chave
    # 2 - criar uma lista com todas as mensagens
    # 3 - montar a arvore
    # 3.1 - para cada email procure sua referencia no dicionario
    #       se achar adiciona o email ao email que ele referencia e remove ele da lista
    #       se nao, nao faz nada
    # 3.2 - os emails que sobrarem na lista sao os filhos do dummy root
    
    # tratar agrupamento por subject
    # 1 - varrer o children do dummy root
    # 2 - quem nao começar com RE: ou Re: ou RE[numero] ou ..., colocar numa lista
    # 3 - quem começar com os REs procurar pelo subject sem RE e adicionar o nó ao que nao tem RE
    # 4 - atribuir a nova lista ao children do root
    
    # tratar mensagens do tipo RE: [alguma coisa] subject
    
    def make_tree(self, email_list):
        tree = Tree()
        node_list = []
        email_dict = {}
        root = tree.add(None)
        pending_emails = []
        
        # creating node list
        for email in email_list:
            node_list.append(TreeNode(email))
        
        # creating dictionary
        for node in node_list:
            if node.elem["message-id"] == None:
                continue
                
            email_dict[node.elem["message-id"]] = node
            
        
        for node in email_dict.values():
            if node.elem["references"] is not None:
                reference = node.elem["references"].split()[-1]
            elif node.elem["in-reply-to"] is not None:
                reference = node.elem["in-reply-to"]
            else:
                reference = None
                
            try:
                node_to_add = email_dict[reference]
            except KeyError:
                continue
            else:
                node_to_add.children.append(node)
                node.parent = node_to_add
                node_list.remove(node)
        
        
        # grouping by subject
        root_children = []
        to_add_nodes = []
        
        for node in node_list:
            if re.match("^R[eE](\[.+\])?:.*$", node.elem["subject"]):
                to_add_nodes.append(node)
            elif re.match("^\[jira\] ((Updated)|(Commented)|(Assigned)|(Closed)|(Resolved)):.*$", node.elem["subject"]):
                to_add_nodes.append(node)            
            else:
                root_children.append(node)
                
        for node in to_add_nodes:
            subject_stripped = re.sub("^R[eE](\[.+\])?:(.*\[.+\])?", "", node.elem["subject"]).strip()
            
            subject_stripped = re.sub("^\[jira\] ((Updated)|(Commented)|(Assigned)|(Closed)|(Resolved)): ", "", subject_stripped)

            
            parent = None            
            for child in root_children:
                child_subject = re.sub("^R[eE](\[.+\])?:(.*\[.+\])?", "", child.elem["subject"]).strip()
                
                child_subject = re.sub("^\[jira\] Created: ", "", child_subject)


                if child_subject == subject_stripped:
                    parent = child
                    break
            
            if parent == None:
                root_children.append(node)
            else:
                parent.children.append(node)
                        
        root.children = root_children   
    
        return tree
                
